﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace YArchitech.HVAC.LevelIndependentTag
{
	public class LevelIndependentTagOperate
	{
		public LevelIndependentTagOperate(Autodesk.Revit.DB.Document Doc)
		{
			this.doc = Doc;
		}

		public LevelIndependentTagOperate(ExternalCommandData commandData, FrmLevelIndependentTag frmLevIndTag)
		{
			this.commandData = commandData;
			this.frmLevIndTag = frmLevIndTag;
			this.uiDoc = this.commandData.Application.ActiveUIDocument;
			this.doc = this.uiDoc.Document;
			this.markOperation = new MarkOperation();
			this.commFont = frmLevIndTag.CommomFont;
		}

		public void Execute(bool isPlane)
		{
			for (;;)
			{
				try
				{
					if (isPlane)
					{
						this.PlanePipeLevelTag();
					}
					else
					{
						this.ThreeDPipeLevelTag();
					}
					this.doc.Regenerate();
					continue;
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
				{
					ex.ToString();
					if (!this.frmLevIndTag.ContorlProcess)
					{
						this.ContorFromRdo();
						continue;
					}
				}
				catch (Exception ex2)
				{
					ex2.ToString();
					continue;
				}
				finally
				{
					if (this.transaction != null && ((int)this.transaction.GetStatus() == 1 || (int)this.transaction.GetStatus() == 5))
					{
						this.transaction.RollBack();
					}
					this.newgrpElements.Clear();
				}
				break;
			}
		}

		private void SetProjectPresice()
		{
			using (Transaction transaction = new Transaction(this.doc, "设置精度"))
			{
				transaction.Start();
				this.markOperation.SetMarkAccuracy(this.doc, this.frmLevIndTag.CommomFont.Presice);
				transaction.Commit();
			}
		}

		private void ContorFromRdo()
		{
			this.frmLevIndTag.ContorlDisable();
			if (!this.frmLevIndTag.rdoOnLine.Enabled || !this.frmLevIndTag.rdoBelowLine.Enabled)
			{
				this.frmLevIndTag.rdoOnLine.Checked = false;
				this.frmLevIndTag.rdoBelowLine.Checked = false;
				return;
			}
			if (!this.frmLevIndTag.rdoOnLine.Checked && !this.frmLevIndTag.rdoBelowLine.Checked)
			{
				this.frmLevIndTag.rdoOnLine.Checked = true;
			}
		}

		private void ThreeDPipeLevelTag()
		{
			this.transaction = new Transaction(this.doc, "管道标高标注");
			this.transaction.Start();
			this.InitialParams();
			this.elem = this.GetTagElement(out this.ptLocation);
			this.SetElemsPara(new List<Element>
			{
				this.elem
			});
			this.MarkSinglePipe3D(this.commFont.TubeDistance);
			this.transaction.Commit();
		}

		private void PlanePipeLevelTag()
		{
			this.transaction = new Transaction(this.doc, "管道标高标注");
			this.transaction.Start();
			this.InitialParams();
			this.SelectedElement();
			this.LayTagFamily();
			this.CreateTagLines();
			this.transaction.Commit();
			this.transaction = new Transaction(this.doc, "管道标高标注创建详图组");
			this.transaction.Start();
			this.CerateTagLinesGroup();
			this.transaction.Commit();
		}

		private void SelectedElement()
		{
			this.fs = this.GetFamilySymbol(this.pipeOffsetMarkSet.Content);
			if (this.pipeLevTagSet.TagModel)
			{
				this.SinglePipeLevelIndepentTag();
				return;
			}
			this.MultiPipeLevelIndepentTag();
		}

		private void InitialParams()
		{
			this.pipeLevTagSet = this.frmLevIndTag.pipeLevTagSet;
			this.pipeOffsetMarkSet = this.frmLevIndTag.PipeOffsetMarkSetting;
			this.frmLevIndTag.ContorlProcess = true;
			this.disToLine = this.commFont.LeadDistance;
			this.textAlign = this.commFont.Align;
			MarkPipeLevelUtility.leadDistance = this.disToLine;
		}

		private void SinglePipeLevelIndepentTag()
		{
			if (this.pipeLevTagSet.TagModel && !this.pipeLevTagSet.TagType && !this.pipeLevTagSet.TagStyle)
			{
				this.elem = this.GetTagElement(out this.ptLocation);
				this.SetElemsPara(new List<Element>
				{
					this.elem
				});
				this.hyLine = this.GetElementLocaCurveHyLine(this.elem);
				this.SetElemsPara(new List<Element>
				{
					this.elem
				});
				string maxTextContent = this.GetMaxTextContent(new List<Element>
				{
					this.elem
				});
				this.markOperation.GetTagTextWidthAndHeight(maxTextContent, this.doc, ref this.tagWidth, ref this.tagHgith);
				if (RevitVersion.GetVersionNumber(this.doc) == "2015" || RevitVersion.GetVersionNumber(this.doc) == "2014")
				{
					this.tagWidth = (double)maxTextContent.Length * this.tagHgith * this.commFont.FontGWRotia * 0.36;
				}
				this.tagWidth = this.tagWidth * 100.0 / (double)this.doc.ActiveView.Scale;
				this.tagHgith = 0.8 * this.tagHgith * 100.0 / (double)this.doc.ActiveView.Scale;
				return;
			}
			this.SingleDynamicShow();
		}

		private void MultiPipeLevelIndepentTag()
		{
			if (this.pipeLevTagSet.TagStyle)
			{
				this.GetPipeByTwoPoint();
				if (this.selectElements.Count < 1)
				{
					YJKMessageBox.Show("您选中的管道不符合要求....");
					return;
				}
				this.MutilDynamicShow();
				return;
			}
			else
			{
				this.selectElements = this.GetTagElements();
				if (this.selectElements.Count < 1)
				{
					YJKMessageBox.Show("您选中的管道不符合要求....");
					return;
				}
				this.SetElemsPara(this.selectElements);
				this.elemIds = this.GetSelectedElemsIdIntergerValue();
				this.elem = this.selectElements.ElementAt(0);
				this.hyLine = this.GetElementLocaCurveHyLine(this.selectElements.ElementAt(0));
				this.ptLocation = (this.hyLine.StartPoint + this.hyLine.EndPoint) / 2.0;
				string maxTextContent = this.GetMaxTextContent(this.selectElements);
				this.markOperation.GetTagTextWidthAndHeight(maxTextContent, this.doc, ref this.tagWidth, ref this.tagHgith);
				if (RevitVersion.GetVersionNumber(this.doc) == "2015" || RevitVersion.GetVersionNumber(this.doc) == "2014")
				{
					this.tagWidth = (double)maxTextContent.Length * this.tagHgith * this.commFont.FontGWRotia * 0.36;
				}
				this.tagWidth = this.tagWidth * 100.0 / (double)this.doc.ActiveView.Scale;
				this.tagHgith = 0.8 * this.tagHgith * 100.0 / (double)this.doc.ActiveView.Scale;
				return;
			}
		}

		private Element GetTagElement(out XYZ basePoint)
		{
			Reference reference = this.uiDoc.Selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, new PipeFilter(), "请选择需要标注的管道...");
			basePoint = reference.GlobalPoint;
			return this.doc.GetElement(reference.ElementId);
		}

		private List<Element> GetTagElements()
		{
			this.parallelPipes.Clear();
			return this.uiDoc.Selection.PickElementsByRectangle(new PipeFilter(), "请框选需要标注的管道...").ToList<Element>();
		}

		private void GetPipeByTwoPoint()
		{
			Selection selection = this.uiDoc.Selection;
			List<Element> list = new FilteredElementCollector(this.doc, this.doc.ActiveView.Id).OfClass(typeof(Pipe)).ToElements().ToList<Element>();
			XYZ xyz = selection.PickPoint("该功能标注两点连线所穿过的所有水管。请选择第一个点......");
			XYZ secPnt;
			using (DrawLineJin drawLineJin = new DrawLineJin(this.uiDoc))
			{
				drawLineJin.StartPoint = xyz;
				secPnt = selection.PickPoint("该功能标注两点连线所穿过的所有水管。请选择第二个点......");
				drawLineJin.Dispose();
			}
			List<Element> list2 = new List<Element>();
			foreach (Element element in list)
			{
				if (!element.IsHidden(this.doc.ActiveView))
				{
					LocationCurve locationCurve = element.Location as LocationCurve;
					XYZ endPoint = locationCurve.Curve.GetEndPoint(0);
					XYZ endPoint2 = locationCurve.Curve.GetEndPoint(1);
					if (YJKRevitTools.IsLineSegmentCross(xyz, secPnt, endPoint, endPoint2))
					{
						list2.Add(element);
					}
				}
			}
			this.ptLocation = secPnt;
			this.selectElements = this.GetOrderElements(this.OrderElementByDistance(list2));
			this.tagLines = this.GetMutilSelectedLine();
			this.CreateTagLines();
		}

		private void SingleDynamicShow()
		{
			this.elem = this.GetTagElement(out this.ptLocation);
			this.SetElemsPara(new List<Element>
			{
				this.elem
			});
			string maxTextContent = this.GetMaxTextContent(new List<Element>
			{
				this.elem
			});
			this.markOperation.GetTagTextWidthAndHeight(maxTextContent, this.doc, ref this.tagWidth, ref this.tagHgith);
			if (RevitVersion.GetVersionNumber(this.doc) == "2015" || RevitVersion.GetVersionNumber(this.doc) == "2014")
			{
				this.tagWidth = (double)maxTextContent.Length * this.tagHgith * this.commFont.FontGWRotia * 0.36;
			}
			MarkPipeLevelUtility.lineLenght = 0.95 * this.tagWidth * this.commFont.LeadRotia * 100.0 / (double)this.doc.ActiveView.Scale;
			MarkPipeLevelUtility.fontHigtht = 0.8 * this.tagHgith * 100.0 / (double)this.doc.ActiveView.Scale;
			this.tagWidth = this.tagWidth * 100.0 / (double)this.doc.ActiveView.Scale;
			this.tagHgith = 0.8 * this.tagHgith * 100.0 / (double)this.doc.ActiveView.Scale;
			this.hyLine = this.GetElementLocaCurveHyLine(this.elem);
			using (CreatePipeLevelLinesJin createPipeLevelLinesJin = new CreatePipeLevelLinesJin(this.uiDoc, this.doc.ActiveView, this.hyLine, true, this.pipeLevTagSet.TagType, this.pipeLevTagSet.TagStyle))
			{
				createPipeLevelLinesJin.movingDistance = this.elem.GetParameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble() / 2.0;
				createPipeLevelLinesJin.StartPoint = this.ptLocation;
				createPipeLevelLinesJin.selectedElements = new List<Element>
				{
					this.elem
				};
				string text = this.pipeLevTagSet.TagStyle ? "请选择标注位置..." : "请选择标注方向...";
				this.uiDoc.Selection.PickPoint(text);
				this.ptLocation = createPipeLevelLinesJin.TagLocation;
				this.tagDirection = createPipeLevelLinesJin.directionVector;
				this.tagLines = createPipeLevelLinesJin.resultLines;
				createPipeLevelLinesJin.Dispose();
			}
		}

		private void MutilDynamicShow()
		{
			this.SetElemsPara(this.selectElements);
			string maxTextContent = this.GetMaxTextContent(this.selectElements);
			this.markOperation.GetTagTextWidthAndHeight(maxTextContent, this.doc, ref this.tagWidth, ref this.tagHgith);
			if (RevitVersion.GetVersionNumber(this.doc) == "2015" || RevitVersion.GetVersionNumber(this.doc) == "2014")
			{
				this.tagWidth = (double)maxTextContent.Length * this.tagHgith * this.commFont.FontGWRotia * 0.36;
			}
			MarkPipeLevelUtility.lineLenght = 0.95 * this.tagWidth * this.commFont.LeadRotia * 100.0 / (double)this.doc.ActiveView.Scale;
			MarkPipeLevelUtility.fontHigtht = 0.8 * this.tagHgith * 100.0 / (double)this.doc.ActiveView.Scale;
			this.tagWidth = this.tagWidth * 100.0 / (double)this.doc.ActiveView.Scale;
			this.tagHgith = 0.8 * this.tagHgith * 100.0 / (double)this.doc.ActiveView.Scale;
			using (CreatePipeLevelLinesJin createPipeLevelLinesJin = new CreatePipeLevelLinesJin(this.uiDoc, this.doc.ActiveView, this.hyLine, false, this.pipeLevTagSet.TagType, this.pipeLevTagSet.TagStyle))
			{
				createPipeLevelLinesJin.selectedElements = this.selectElements;
				createPipeLevelLinesJin.StartPoint = this.ptLocation;
				createPipeLevelLinesJin.mutilDirection = this.mutilDirection;
				this.uiDoc.Selection.PickPoint("请选择标注位置...");
				this.ptLocation = createPipeLevelLinesJin.TagLocation;
				this.tagDirection = createPipeLevelLinesJin.directionVector;
				this.tagLines = createPipeLevelLinesJin.resultLines;
				createPipeLevelLinesJin.Dispose();
			}
		}

		private void CreateTagLines()
		{
			for (int i = 0; i < this.tagLines.Count; i++)
			{
				DetailCurve detailCurve = this.doc.CreatYJKDetailCurve(this.tagLines.ElementAt(i));
				this.newgrpElements.Insert(detailCurve);
				for (int j = 0; j < RevitVersionFuncs.LineStyles(this.doc, detailCurve).Size; j++)
				{
					GraphicsStyle graphicsStyle = RevitVersionFuncs.LineStyles(this.doc, detailCurve).get_Item(j) as GraphicsStyle;
					int hashCode = -2000042.GetHashCode();
					if (graphicsStyle.GraphicsStyleCategory.GetHashCode() == hashCode)
					{
						detailCurve.LineStyle = graphicsStyle;
						break;
					}
				}
			}
		}

		private void CreateDownLine(int selectedCount, double maxLenth)
		{
			for (int i = 0; i < selectedCount; i++)
			{
				DetailCurve detailCurve = this.doc.CreatYJKDetailCurve(YJKLineEx.YJKGetBound(this.ptLocation + (double)i * AssistFunc.mmToFeet(this.fontHigtht * (400.0 + this.disToLine * 100.0)) * this.tagDirection.VerticalVector * ((double)this.doc.ActiveView.Scale / 100.0), this.ptLocation + (double)i * AssistFunc.mmToFeet(this.fontHigtht * (400.0 + this.disToLine * 100.0)) * this.tagDirection.VerticalVector * ((double)this.doc.ActiveView.Scale / 100.0) + AssistFunc.mmToFeet(this.fontHigtht * this.fontWidth * maxLenth) * this.tagDirection.HorizontalVector * ((double)this.doc.ActiveView.Scale / 100.0)));
				this.newgrpElements.Insert(detailCurve);
				int num = 0;
				while (i < RevitVersionFuncs.LineStyles(this.doc, detailCurve).Size)
				{
					GraphicsStyle graphicsStyle = RevitVersionFuncs.LineStyles(this.doc, detailCurve).get_Item
                    (num) as GraphicsStyle;
					int hashCode = -2000042.GetHashCode();
					if (graphicsStyle.GraphicsStyleCategory.GetHashCode() == hashCode)
					{
						detailCurve.LineStyle = graphicsStyle;
						break;
					}
					num++;
				}
			}
		}

		private void CerateTagLinesGroup()
		{
			if (this.newgrpElements.Size < 1)
			{
				return;
			}
			AssociationMarkInfo.WriteMarkInfoToElement(RevitVersionFuncs.NewGroup(this.doc, this.newgrpElements), MarkType.PipeLevel);
		}

		private void LayTagFamily()
		{
			if (this.pipeLevTagSet.TagModel)
			{
				this.SinglePipeLayTagFamily();
				return;
			}
			this.MutilePipeLayTagFamily();
		}

		private void MutilePipeLayTagFamily()
		{
			int maxTextLenth = this.GetMaxTextLenth(this.selectElements);
			MarkOperation markOperation = new MarkOperation();
			if (this.pipeLevTagSet.TagType)
			{
				for (int i = 0; i < this.selectElements.Count; i++)
				{
					Element element = this.selectElements.ElementAt(i);
					IndependentTag independentTag = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(element), false, 0, 0, this.ptLocation + this.CalculateTagPosition(this.disToLine, maxTextLenth) + (double)i * AssistFunc.mmToFeet(this.tagHgith + this.disToLine * 2.0) * this.tagDirection.VerticalVector * (double)this.doc.ActiveView.Scale / 100.0);
					independentTag.ChangeTypeId(this.fs.Id);
					AssociationMarkInfo.WriteMarkInfoToElement(independentTag, MarkType.PipeLevel);
					if (MarkPipeLevelUtility.leaderLines.Count == this.selectElements.Count)
					{
						YJKLine hyline = new YJKLine(MarkPipeLevelUtility.leaderLines[i]);
						markOperation.SetAlignStyle(independentTag, hyline, this.ptLocation, "水管标高");
					}
				}
			}
			if (!this.pipeLevTagSet.TagType && this.pipeLevTagSet.TagStyle)
			{
				int num = 0;
				if (this.tagDirection.VerticalVector.AngleTo(this.doc.ActiveView.UpDirection) > Math.PI*.5)
				{
					num = -1;
					for (int j = 0; j < this.selectElements.Count; j++)
					{
						Element element = this.selectElements.ElementAt(j);
						XYZ pnt = this.ptLocation + this.CalculateTagPosition(this.disToLine, maxTextLenth) + (double)(num + j) * AssistFunc.mmToFeet(this.tagHgith + this.disToLine * 2.0) * this.tagDirection.VerticalVector * (double)this.doc.ActiveView.Scale / 100.0 + AssistFunc.mmToFeet(this.tagHgith * 0.5) * this.tagDirection.VerticalVector * (double)this.doc.ActiveView.Scale / 100.0;
						IndependentTag independentTag2 = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(this.selectElements.ElementAt(j)), false, 0, 0, pnt);
						independentTag2.ChangeTypeId(this.fs.Id);
						AssociationMarkInfo.WriteMarkInfoToElement(independentTag2, MarkType.PipeLevel);
						if (MarkPipeLevelUtility.leaderLines.Count == this.selectElements.Count)
						{
							YJKLine hyline2 = new YJKLine(MarkPipeLevelUtility.leaderLines[j]);
							markOperation.SetAlignStyle(independentTag2, hyline2, this.ptLocation, "水管标高");
						}
					}
				}
				else
				{
					for (int k = 0; k < this.selectElements.Count; k++)
					{
						Element element = this.selectElements.ElementAt(k);
						IndependentTag independentTag3 = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(this.selectElements.ElementAt(k)), false, 0, 0, this.ptLocation + this.CalculateTagPosition(this.disToLine, maxTextLenth) + (double)(num + k) * AssistFunc.mmToFeet(this.tagHgith + this.disToLine * 2.0) * this.tagDirection.VerticalVector * (double)this.doc.ActiveView.Scale / 100.0);
						independentTag3.ChangeTypeId(this.fs.Id);
						AssociationMarkInfo.WriteMarkInfoToElement(independentTag3, MarkType.PipeLevel);
						if (MarkPipeLevelUtility.leaderLines.Count == this.selectElements.Count)
						{
							YJKLine hyline3 = new YJKLine(MarkPipeLevelUtility.leaderLines[k]);
							markOperation.SetAlignStyle(independentTag3, hyline3, this.ptLocation, "水管标高");
						}
					}
				}
			}
			if (!this.pipeLevTagSet.TagType && !this.pipeLevTagSet.TagStyle)
			{
				this.GroupingByElemsParallel();
				foreach (List<Element> list in this.parallelPipes)
				{
					double num2 = double.MaxValue;
					foreach (Element element2 in list)
					{
						this.hyLine = this.GetElementLocaCurveHyLine(element2);
						if (this.hyLine.Line.Length < num2)
						{
							num2 = this.hyLine.Line.Length;
							this.ptLocation = (this.hyLine.StartPoint + this.hyLine.EndPoint) / 2.0;
						}
					}
					foreach (Element element3 in list)
					{
						this.hyLine = this.GetElementLocaCurveHyLine(element3);
						IndependentTag independentTag4 = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(element3), false, 0, 0, this.CalculateTagPosition(this.commFont.TubeDistance, 0));
						independentTag4.ChangeTypeId(this.fs.Id);
						AssociationMarkInfo.WriteMarkInfoToElement(independentTag4, MarkType.PipeLevel);
					}
				}
			}
		}

		private void SinglePipeLayTagFamily()
		{
			if (this.pipeLevTagSet.TagType || this.pipeLevTagSet.TagStyle)
			{
				int maxTextLenth = this.GetMaxTextLenth(new List<Element>
				{
					this.elem
				});
				XYZ xyz = this.CalculateTagPosition(this.disToLine, maxTextLenth);
				XYZ xyz2 = this.ptLocation + xyz;
				if (!this.pipeLevTagSet.TagType && this.pipeLevTagSet.TagStyle && this.tagDirection.VerticalVector.AngleTo(this.doc.ActiveView.UpDirection) > Math.PI*.5)
				{
					xyz2 -= AssistFunc.mmToFeet(0.5 * this.tagHgith + this.disToLine * 2.0) * this.tagDirection.VerticalVector * (double)this.doc.ActiveView.Scale / 100.0;
				}
				IndependentTag independentTag = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(this.elem), false, 0, 0, xyz2);
				independentTag.ChangeTypeId(this.fs.Id);
				AssociationMarkInfo.WriteMarkInfoToElement(independentTag, MarkType.PipeLevel);
				if (independentTag != null)
				{
					MarkOperation markOperation = new MarkOperation();
					if (MarkPipeLevelUtility.leaderLines.Count > 0)
					{
						YJKLine hyline = new YJKLine(MarkPipeLevelUtility.leaderLines.First<Line>());
						markOperation.SetAlignStyle(independentTag, hyline, this.ptLocation, "水管标高");
						return;
					}
				}
			}
			else
			{
				IndependentTag independentTag = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(this.elem), false, 0, 0, this.CalculateTagPosition(this.commFont.TubeDistance, 0));
				independentTag.ChangeTypeId(this.fs.Id);
				AssociationMarkInfo.WriteMarkInfoToElement(independentTag, MarkType.PipeLevel);
			}
		}

		private int GetMaxTextLenth(List<Element> listElements)
		{
			int num = 0;
			for (int i = 0; i < listElements.Count; i++)
			{
				IndependentTag independentTag = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(listElements.ElementAt(i)), false, 0, 0, this.ptLocation);
				independentTag.ChangeTypeId(this.fs.Id);
				if (num < independentTag.TagText.Length)
				{
					num = independentTag.TagText.Length;
					string tagText = independentTag.TagText;
				}
				this.doc.DeleteElement(independentTag);
			}
			return num;
		}

		private string GetMaxTextContent(List<Element> listElements)
		{
			int num = 0;
			string result = "";
			for (int i = 0; i < listElements.Count; i++)
			{
				IndependentTag independentTag = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(listElements.ElementAt(i)), false, 0, 0, this.ptLocation);
				independentTag.ChangeTypeId(this.fs.Id);
				if (num < independentTag.TagText.Length)
				{
					num = independentTag.TagText.Length;
					result = independentTag.TagText;
				}
				this.doc.DeleteElement(independentTag);
			}
			return result;
		}

		private XYZ CalculateTagPosition(double distancToPipe, int textLength)
		{
			if (this.pipeLevTagSet.TagType || this.pipeLevTagSet.TagStyle)
			{
				double num = 1.0;
				if (this.tagDirection.HorizontalVector.AngleTo(this.doc.ActiveView.RightDirection) > Math.PI*.5)
				{
					num = 0.5;
				}
				return AssistFunc.mmToFeet(this.tagWidth * this.commFont.LeadRotia / 2.0 - num * 40.0) * this.tagDirection.HorizontalVector * (double)this.doc.ActiveView.Scale / 100.0 + AssistFunc.mmToFeet(0.5 * this.tagHgith / 2.0 + distancToPipe) * this.tagDirection.VerticalVector * (double)this.doc.ActiveView.Scale / 100.0;
			}
			XYZ project = this.hyLine.GetProject(this.ptLocation);
			XYZ xyz = YJKRevitTools.GetVectorByHorizontal((this.hyLine.EndPoint - this.hyLine.StartPoint).Normalize());
			if (project.Y > (project + xyz * 2.0).Y)
			{
				xyz = -1.0 * xyz;
			}
			double num2 = ((int)this.doc.ActiveView.DetailLevel == 3) ? ((this.elem as Pipe).Diameter / 2.0 + (distancToPipe + 0.5 * this.tagHgith / 2.0) / 304.8 * ((double)YJKRevitTools.GetViewPlanScale(this.doc) / 100.0)) : ((distancToPipe + 0.5 * this.tagHgith / 2.0) / 304.8 * ((double)YJKRevitTools.GetViewPlanScale(this.doc) / 100.0));
			if (!this.pipeLevTagSet.tagLocation)
			{
				num2 += 0.098658247829518556 * ((double)YJKRevitTools.GetViewPlanScale(this.doc) / 100.0);
				return project - num2 * xyz;
			}
			return project + num2 * xyz;
		}

		private XYZ CalMovingDistanceByAlign(XYZ centerPoint, int textLength)
		{
			XYZ result = XYZ.Zero;
			double val = Math.Abs((MarkPipeLevelUtility.lineLenght - (double)textLength) / 2.0);
			string a = this.textAlign;
			if (!(a == "始端对齐"))
			{
				if (!(a == "末端对齐"))
				{
					if (!(a == "居中对齐"))
					{
					}
					result = centerPoint;
				}
				else
				{
					result = centerPoint + 0.6 * this.tagDirection.HorizontalVector * AssistFunc.mmToFeet(val) * (double)this.doc.ActiveView.Scale / 100.0;
				}
			}
			else
			{
				result = centerPoint - 0.6 * this.tagDirection.HorizontalVector * AssistFunc.mmToFeet(val) * (double)this.doc.ActiveView.Scale / 100.0;
			}
			return result;
		}

		private FamilySymbol GetFamilySymbol(string levelType)
		{
			if (levelType == "绝对标高" || string.IsNullOrEmpty(levelType))
			{
				if (!this.pipeOffsetMarkSet.Suffix.Equals("m"))
				{
					return this.GetFamilySymbolyByName("MarkTag", "HY_水管绝对标高标注_毫米.rfa");
				}
				if (this.commFont.Presice.Length != 4)
				{
					return this.GetFamilySymbolyByName("MarkTag", "HY_水管绝对标高标注_三位小数.rfa");
				}
				return this.GetFamilySymbolyByName("MarkTag", "HY_水管绝对标高标注_两位小数.rfa");
			}
			else
			{
				if (!this.pipeOffsetMarkSet.Suffix.Equals("m"))
				{
					return this.GetFamilySymbolyByName("MarkTag", "HY_水管相对标高标注_毫米.rfa");
				}
				if (this.commFont.Presice.Length != 4)
				{
					return this.GetFamilySymbolyByName("MarkTag", "HY_水管相对标高标注_三位小数.rfa");
				}
				return this.GetFamilySymbolyByName("MarkTag", "HY_水管相对标高标注_两位小数.rfa");
			}
		}

		public FamilySymbol GetFamilySymbolyByName(string typeName, string familyName)
		{
			FamilySymbol result = null;
			string text = Path.Combine(Product.FamilyLocation, RevitVersion.GetVersionNumber(this.doc), typeName, familyName);
			Family family = null;
			SubTransaction subTransaction = null;
			try
			{
				foreach (Element element in YJKElementFilter.GetElementByCategory(this.doc, typeof(FamilySymbol), BuiltInCategory.OST_PipeTags))
				{
					if ((element as FamilySymbol).Family.Name == familyName.Substring(0, familyName.IndexOf(".")))
					{
						FamilySymbol result2;
						result = (result2 = (element as FamilySymbol));
						return result2;
					}
				}
				subTransaction = new SubTransaction(this.doc);
				subTransaction.Start();
				this.doc.LoadFamily(text, out family);
				subTransaction.Commit();
			}
			catch (Exception)
			{
			}
			finally
			{
				if (subTransaction != null && (int)subTransaction.GetStatus() != 3)
				{
					subTransaction.RollBack();
				}
			}
			if (family != null)
			{
				using (List<FamilySymbol>.Enumerator enumerator2 = family.GetSymbols().GetEnumerator())
				{
					if (enumerator2.MoveNext())
					{
						result = enumerator2.Current;
					}
				}
			}
			return result;
		}

		public FamilySymbol GetFamilySymbolyByName(string typeName, string familyName, string symbolName)
		{
			FamilySymbol result = null;
			string text = Path.Combine(Product.FamilyLocation, RevitVersion.GetVersionNumber(this.doc), typeName, familyName);
			Family family = null;
			SubTransaction subTransaction = null;
			try
			{
				foreach (Element element in YJKElementFilter.GetElementByCategory(this.doc, typeof(FamilySymbol), BuiltInCategory.OST_PipeTags))
				{
					if ((element as FamilySymbol).Family.Name == familyName.Substring(0, familyName.IndexOf(".")) && (element as FamilySymbol).Name.Replace("（", "(").Replace("）", ")") == symbolName.Replace("（", "(").Replace("）", ")"))
					{
						FamilySymbol result2;
						result = (result2 = (element as FamilySymbol));
						return result2;
					}
				}
				subTransaction = new SubTransaction(this.doc);
				subTransaction.Start();
				this.doc.LoadFamily(text, new MyFamilyLoadOptions(), out family);
				subTransaction.Commit();
			}
			catch (Exception)
			{
			}
			finally
			{
				if (subTransaction != null && (int)subTransaction.GetStatus() != 3)
				{
					subTransaction.RollBack();
				}
			}
			if (family != null)
			{
				foreach (FamilySymbol familySymbol in family.GetSymbols())
				{
					if (familySymbol.Family.Name == familyName.Substring(0, familyName.IndexOf(".")) && familySymbol.Name.Replace("（", "(").Replace("）", ")") == symbolName.Replace("（", "(").Replace("）", ")"))
					{
						result = familySymbol;
						break;
					}
				}
			}
			return result;
		}

		public FamilySymbol GetDuctTagByName(string typeName, string familyName, string symbolName, bool isSplit = false)
		{
			FamilySymbol result = null;
			if (familyName == "HY_风管标注_绝对标高_两位小数.rfa" && isSplit)
			{
				familyName = "HY_风管标注_绝对标高_空格_两位小数.rfa";
			}
			else if (familyName == "HY_风管标注_相对标高_两位小数.rfa" && isSplit)
			{
				familyName = "HY_风管标注_相对标高_空格_两位小数.rfa";
			}
			else if (familyName == "HY_风管标注_绝对标高_三位小数.rfa" && isSplit)
			{
				familyName = "HY_风管标注_绝对标高_空格_三位小数.rfa";
			}
			else if (familyName == "HY_风管标注_相对标高_三位小数.rfa" && isSplit)
			{
				familyName = "HY_风管标注_相对标高_空格_三位小数.rfa";
			}
			else if (familyName == "HY_水管相对标高标注_毫米.rfa" && isSplit)
			{
				familyName = "HY_风管标注_相对标高_空格_三位小数.rfa";
			}
			string text = Path.Combine(Product.FamilyLocation, RevitVersion.GetVersionNumber(this.doc), typeName, familyName);
			Family family = null;
			SubTransaction subTransaction = null;
			try
			{
				foreach (Element element in YJKElementFilter.GetElementByCategory(this.doc, typeof(FamilySymbol), BuiltInCategory.OST_DuctTags))
				{
					if ((element as FamilySymbol).Family.Name == familyName.Substring(0, familyName.IndexOf(".")) && (element as FamilySymbol).Name == symbolName)
					{
						FamilySymbol result2;
						result = (result2 = (element as FamilySymbol));
						return result2;
					}
				}
				subTransaction = new SubTransaction(this.doc);
				subTransaction.Start();
				this.doc.LoadFamily(text, out family);
				subTransaction.Commit();
			}
			catch (Exception)
			{
			}
			finally
			{
				if (subTransaction != null && (int)subTransaction.GetStatus() != 3)
				{
					subTransaction.RollBack();
				}
			}
			if (family != null)
			{
				foreach (FamilySymbol familySymbol in family.GetSymbols())
				{
					if (familySymbol.Family.Name == familyName.Substring(0, familyName.IndexOf(".")) && familySymbol.Name == symbolName)
					{
						result = familySymbol;
						break;
					}
				}
			}
			return result;
		}

		private YJKLine GetElementLocaCurveHyLine(Element element)
		{
			LocationCurve locationCurve = element.Location as LocationCurve;
			XYZ endPoint = locationCurve.Curve.GetEndPoint(0);
			XYZ endPoint2 = locationCurve.Curve.GetEndPoint(1);
			XYZ xyz = new XYZ(endPoint.X, endPoint.Y, 0.0);
			XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, 0.0);
			YJKLine result;
			if ((xyz2 - xyz).AngleTo(this.doc.ActiveView.RightDirection) <= Math.PI*.5)
			{
				result = new YJKLine(xyz, xyz2);
			}
			else
			{
				result = new YJKLine(xyz2, xyz);
			}
			return result;
		}

		private Dictionary<Element, double> OrderElementByDistance(List<Element> elems)
		{
			Dictionary<Element, double> dictionary = new Dictionary<Element, double>();
			XYZ xyz = new XYZ(this.ptLocation.X, this.ptLocation.Y, 0.0);
			foreach (Element element in elems)
			{
				YJKLine elementLocaCurveHyLine = this.GetElementLocaCurveHyLine(element);
				elementLocaCurveHyLine.MakeUnBound();
				XYZ project = elementLocaCurveHyLine.GetProject(xyz);
				double length = Line.CreateBound(xyz, project).Length;
				dictionary.Add(element, length);
			}
			return (from p in dictionary
			orderby p.Value descending
			select p).ToDictionary((KeyValuePair<Element, double> p) => p.Key, (KeyValuePair<Element, double> p) => p.Value);
		}

		private List<Element> GetOrderElements(Dictionary<Element, double> dic)
		{
			List<Element> list = new List<Element>();
			foreach (KeyValuePair<Element, double> keyValuePair in dic)
			{
				list.Add(keyValuePair.Key);
			}
			return list;
		}

		private List<Line> GetMutilSelectedLine()
		{
			List<Line> list = new List<Line>();
			this.hyLine = this.GetElementLocaCurveHyLine(this.selectElements.ElementAt(0));
			YJKLine hyline = this.hyLine;
			hyline.MakeUnBound();
			XYZ project = hyline.GetProject(this.ptLocation);
			XYZ xyz = project - (this.ptLocation - project).Normalize() * AssistFunc.mmToFeet(200.0) * ((double)this.doc.ActiveView.Scale / 100.0);
			Line line = YJKLineEx.YJKGetBound(new XYZ(xyz.X, xyz.Y, 0.0), new XYZ(this.ptLocation.X, this.ptLocation.Y, 0.0));
			XYZ xyz2 = (new XYZ(this.hyLine.EndPoint.X, this.hyLine.EndPoint.Y, 0.0) - new XYZ(this.hyLine.StartPoint.X, this.hyLine.StartPoint.Y, 0.0)).Normalize();
			XYZ xyz3 = (new XYZ(this.ptLocation.X, this.ptLocation.Y, 0.0) - new XYZ(project.X, project.Y, 0.0)).Normalize();
			this.mutilDirection = xyz3;
			list.Add(line);
			XYZ xyz4 = (xyz3.AngleTo(this.doc.ActiveView.UpDirection) < Math.PI*.5) ? (xyz2 - xyz3).Normalize() : (xyz2 + xyz3).Normalize();
			foreach (Element element in this.selectElements)
			{
				YJKLine elementLocaCurveHyLine = this.GetElementLocaCurveHyLine(element);
				elementLocaCurveHyLine.MakeUnBound();
				XYZ xyz5 = elementLocaCurveHyLine.IntersectionPoint(line);
				list.Add(Line.CreateBound(xyz5 - AssistFunc.mmToFeet(150.0) * ((double)this.doc.ActiveView.Scale / 100.0) * xyz4, xyz5 + AssistFunc.mmToFeet(150.0) * ((double)this.doc.ActiveView.Scale / 100.0) * xyz4));
			}
			return list;
		}

		private void SetElemsPara(List<Element> elems)
		{
			using (SubTransaction subTransaction = new SubTransaction(this.doc))
			{
				subTransaction.Start();
				foreach (Element element in elems)
				{
					this.SetLevelPrefix(element);
					this.SetLevelSuffix(element);
					if (this.pipeOffsetMarkSet.Content == "绝对标高" || string.IsNullOrEmpty(this.pipeOffsetMarkSet.Content))
					{
						this.SetAbsLevelValue(element);
					}
					else
					{
						this.SetRelativeLevelValue(element);
					}
				}
				subTransaction.Commit();
			}
		}

		private void SetLevelPrefix(Element selectedElem)
		{
			if (this.pipeOffsetMarkSet.Prefix.Contains("无"))
			{
				selectedElem.GetParameter("标高前缀").Set(" ");
				return;
			}
			selectedElem.GetParameter("标高前缀").Set(this.pipeOffsetMarkSet.Prefix);
		}

		private void SetLevelSuffix(Element selectedElem)
		{
			if (this.pipeOffsetMarkSet.UnitVisible == "显示")
			{
				selectedElem.GetParameter("标高后缀").Set(this.pipeOffsetMarkSet.Suffix);
			}
		}

		private void SetAbsLevelValue(Element selectedElem)
		{
			double num = (selectedElem as Pipe).ReferenceLevel.GetParameter(BuiltInParameter.LEVEL_ELEV).AsDouble();
			double levelOffset = (selectedElem as Pipe).LevelOffset;
			double num2 = num + levelOffset;
			if (this.pipeLevTagSet.TagModel)
			{
				double num3 = selectedElem.GetParameter(BuiltInParameter.RBS_START_OFFSET_PARAM).AsDouble();
				double num4 = selectedElem.GetParameter(BuiltInParameter.RBS_END_OFFSET_PARAM).AsDouble();
				YJKLine hyline = new YJKLine((this.elem.Location as LocationCurve).Curve.GetEndPoint(0), (this.elem.Location as LocationCurve).Curve.GetEndPoint(1));
				XYZ project = hyline.GetProject(this.ptLocation);
				if (!project.IsAlmostEqualTo(hyline.StartPoint, 1E-05))
				{
					Line line = Line.CreateBound(hyline.StartPoint, project);
					num2 = num + num3 + line.Length / hyline.Line.Length * (num4 - num3);
				}
				else
				{
					num2 = num + num3;
				}
			}
			Parameter parameter = selectedElem.GetParameter("绝对标高");
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(num2);
			}
			if (Math.Abs(Math.Round(num2, 7)) <= 1E-07)
			{
				selectedElem.GetParameter("标高前缀").Set("±");
			}
			if (Math.Round(num2, 7) > 1E-07)
			{
				selectedElem.GetParameter("标高前缀").Set(" ");
			}
			if (Math.Round(num2, 7) < -1E-07)
			{
				selectedElem.GetParameter("标高前缀").Set(" ");
			}
		}

		private void SetRelativeLevelValue(Element selectedElem)
		{
			double levelOffset = (selectedElem as Pipe).LevelOffset;
			if (Math.Abs(Math.Round(levelOffset, 7)) <= 1E-07)
			{
				selectedElem.GetParameter("标高前缀").Set(selectedElem.GetParameter("标高前缀").AsString() + "±");
			}
			if (Math.Round(levelOffset, 7) > 1E-07)
			{
				if (string.IsNullOrEmpty(selectedElem.GetParameter("标高前缀").AsString().Trim()))
				{
					selectedElem.GetParameter("标高前缀").Set(selectedElem.GetParameter("标高前缀").AsString());
					return;
				}
				selectedElem.GetParameter("标高前缀").Set(selectedElem.GetParameter("标高前缀").AsString() + "＋");
			}
		}

		public IndependentTag MarkSinglePipe3D(double distancToPipe)
		{
			IndependentTag result;
			try
			{
				this.fs = this.GetFamilySymbol(this.pipeOffsetMarkSet.Content);
				LocationCurve locationCurve = this.elem.Location as LocationCurve;
				XYZ xyzpoint = locationCurve.Curve.Project(this.ptLocation).XYZPoint;
				XYZ xyz = YJKRevitTools.GetVectorByHorizontal((locationCurve.Curve.GetEndPoint(1) - locationCurve.Curve.GetEndPoint(0)).Normalize());
				if (xyzpoint.Y > (xyzpoint + xyz * 2.0).Y)
				{
					xyz = -1.0 * xyz;
				}
				double num = ((int)this.doc.ActiveView.DetailLevel == 3) ? ((this.elem as Pipe).Diameter / 2.0 + (distancToPipe + 200.0 + this.tagHgith / 2.0) / 304.8 * ((double)YJKRevitTools.GetViewPlanScale(this.doc) / 100.0)) : ((distancToPipe + 200.0 + this.tagHgith / 2.0) / 304.8 * ((double)YJKRevitTools.GetViewPlanScale(this.doc) / 100.0));
				XYZ pnt;
				if ((int)this.doc.ActiveView.ViewType == 117)
				{
					if (this.pipeLevTagSet.tagLocation)
					{
						pnt = (((int)this.doc.ActiveView.DetailLevel == 3) ? new XYZ(xyzpoint.X, xyzpoint.Y, xyzpoint.Z + (distancToPipe + 200.0 + this.tagHgith / 2.0) / 304.8 * (double)this.doc.ActiveView.Scale / 100.0) : new XYZ(xyzpoint.X, xyzpoint.Y, xyzpoint.Z + (distancToPipe + 200.0 + this.tagHgith / 2.0) / 304.8 * (double)this.doc.ActiveView.Scale / 100.0));
					}
					else
					{
						pnt = (((int)this.doc.ActiveView.DetailLevel == 3) ? new XYZ(xyzpoint.X, xyzpoint.Y, xyzpoint.Z - (distancToPipe + 200.0 + this.tagHgith / 2.0) / 304.8 * (double)this.doc.ActiveView.Scale / 100.0) : new XYZ(xyzpoint.X, xyzpoint.Y, xyzpoint.Z - (distancToPipe + 200.0 + this.tagHgith / 2.0) / 304.8 * (double)this.doc.ActiveView.Scale / 100.0));
					}
				}
				else if (this.pipeLevTagSet.tagLocation)
				{
					pnt = xyzpoint + num * xyz;
				}
				else
				{
					pnt = xyzpoint - num * xyz;
				}
				IndependentTag independentTag = RevitVersionFuncs.NewTag(this.doc, this.doc.ActiveView, new Reference(this.elem), false, 0, 0, pnt);
				independentTag.ChangeTypeId(this.fs.Id);
				AssociationMarkInfo.WriteMarkInfoToElement(independentTag, MarkType.PipeLevel);
				result = independentTag;
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}

		private void SetAbsLevelValue()
		{
		}

		private List<int> GetSelectedElemsIdIntergerValue()
		{
			List<int> list = new List<int>();
			foreach (Element element in this.selectElements)
			{
				list.Add(element.Id.IntegerValue);
			}
			return list;
		}

		private void GroupingByElemsParallel()
		{
			if (this.elemIds.Count == 0)
			{
				return;
			}
			Element element = this.doc.GetElement(new ElementId(this.elemIds.ElementAt(0)));
			List<Element> list = new List<Element>();
			Line line = ((element as Pipe).Location as LocationCurve).Curve as Line;
			foreach (int num in this.elemIds)
			{
				Pipe pipe = this.doc.GetElement(new ElementId(num)) as Pipe;
				Line line2 = (pipe.Location as LocationCurve).Curve as Line;
				if (line.Direction.IsAlmostEqualTo(line2.Direction) || line.Direction.IsAlmostEqualTo(-line2.Direction))
				{
					list.Add(pipe);
				}
			}
			double num2 = double.MaxValue;
			foreach (Element element2 in list)
			{
				this.hyLine = this.GetElementLocaCurveHyLine(element2);
				if (this.hyLine.Line.Length <= num2)
				{
					num2 = this.hyLine.Line.Length;
					this.ptLocation = (this.hyLine.StartPoint + this.hyLine.EndPoint) / 2.0;
				}
			}
			List<Element> list2 = new List<Element>();
			foreach (Element element3 in list)
			{
				YJKLine elementLocaCurveHyLine = this.GetElementLocaCurveHyLine(element3);
				elementLocaCurveHyLine.MakeUnBound();
				XYZ project = elementLocaCurveHyLine.GetProject(this.ptLocation);
				this.hyLine = this.GetElementLocaCurveHyLine(element3);
				if (this.hyLine.IsPointOnLine(project))
				{
					list2.Add(element3);
					this.elemIds.Remove(element3.Id.IntegerValue);
				}
			}
			this.parallelPipes.Add(list2);
			this.GroupingByElemsParallel();
		}

		private void LoadSetFamily()
		{
			this.transaction = new Transaction(this.doc, "加载设置族");
			this.transaction.Start();
			Family family = this.GetFamilySymbolyByName("MarkTag", "HY_水管相对标高标注.rfa").Family;
			Family family2 = this.GetFamilySymbolyByName("MarkTag", "HY_水管绝对标高标注.rfa").Family;
			this.transaction.Commit();
			this.SetFamilyParams(family, family2);
		}

		private void SetFamilyParams(Family relative, Family abs)
		{
			MarkOperation markOperation = new MarkOperation();
			CommonFont commonFont = new CommonFont
			{
				Font = this.frmLevIndTag.CommomFont.Font,
				FontHeight = this.frmLevIndTag.CommomFont.FontHeight,
				Align = this.frmLevIndTag.CommomFont.Align,
				FontGWRotia = this.frmLevIndTag.CommomFont.FontGWRotia,
				LeadDistance = this.frmLevIndTag.CommomFont.LeadDistance,
				LeadRotia = this.frmLevIndTag.CommomFont.LeadRotia,
				Presice = this.frmLevIndTag.CommomFont.Presice,
				TubeDistance = this.frmLevIndTag.CommomFont.TubeDistance
			};
			markOperation.EditHYFamilyFont(relative, commonFont, false);
			markOperation.EditHYFamilyFont(abs, commonFont, false);
		}

		private ExternalCommandData commandData;

		private UIDocument uiDoc;

		private Document doc;

		private FrmLevelIndependentTag frmLevIndTag;

		private FamilySymbol fs;

		private List<Line> tagLines = new List<Line>();

		private ElementSet newgrpElements = new ElementSet();

		private PipeLevelTagSet pipeLevTagSet;

		private Transaction transaction;

		private CommonFont commFont;

		private List<Element> selectElements = new List<Element>();

		private YJKLine hyLine;

		private PipeOffsetMarkSet pipeOffsetMarkSet;

		private Element elem;

		private XYZ ptLocation;

		private DirectionVector tagDirection;

		private XYZ mutilDirection;

		private double fontHigtht = 1.0;

		private double fontWidth = 1.0;

		private List<List<Element>> parallelPipes = new List<List<Element>>();

		private List<int> elemIds = new List<int>();

		private MarkOperation markOperation;

		private double tagWidth;

		private double tagHgith;

		private double disToLine;

		private string textAlign = string.Empty;
	}
}
